/* hlite.c, generic syntax highlighting, Ait Emacs, Kevin Bloom, BSD 3-Clause, 2023 */

#include "header.h"
#include "util.h"

int state = ID_DEFAULT;
int next_state = ID_DEFAULT;
int skip_count = 0;

char_t get_at(buffer_t *bp, point_t pt)
{
  return (*ptr(bp, pt));
}

void set_parse_state(buffer_t *bp, point_t pt)
{
  register point_t po;

  state = ID_DEFAULT;
  next_state = ID_DEFAULT;
  skip_count = 0;

  for (po = 0; po < pt; po++)
    parse_text(bp, po);
}

int parse_text(buffer_t *bp, point_t pt)
{
//  if(bp->b_keywords == NULL)
//    return state;

  if (skip_count-- > 0)
    return state;

  char_t c_now = get_at(bp, pt);
  char_t c_next = get_at(bp, pt + 1);
  state = next_state;

  if (state == ID_DEFAULT &&
      bp->b_keywords != NULL &&
      bp->b_keywords->mlc != NULL &&
      c_now == bp->b_keywords->mlc[0] &&
      c_next == bp->b_keywords->mlc[1]) {
    skip_count = 1;
    return (next_state = state = ID_BLOCK_COMMENT);
  }

  if (state == ID_BLOCK_COMMENT &&
      bp->b_keywords != NULL &&
      bp->b_keywords->emlc != NULL &&
      c_now == bp->b_keywords->emlc[0] &&
      c_next == bp->b_keywords->emlc[1]) {
    skip_count = 1;
    next_state = ID_DEFAULT;
    return ID_BLOCK_COMMENT;
  }

  if (state == ID_DEFAULT &&
      bp->b_keywords != NULL &&
      c_now == bp->b_keywords->slc[0] &&
      c_next == bp->b_keywords->slc[1]) {
    skip_count = 1;
    return (next_state = state = ID_LINE_COMMENT);
  }

  if (state == ID_LINE_COMMENT && c_now == '\n')
    return (next_state = ID_DEFAULT);

  if (state == ID_DEFAULT && c_now == '"') {
    int enable = FALSE;
    char_t z = get_at(bp, pt+1);
    point_t end = pos(bp, bp->b_ebuf);
    for(point_t i = pt+1; z != '\n' && i <= end; i++, z = get_at(bp, i)) {
      if(z == '"') {
        enable = TRUE;
        break;
      }
      if(z == '\\' && get_at(bp, i+1) == '\n') {
        enable = TRUE;
        break;
      }
    }
    if(enable)
      return (next_state = ID_DOUBLE_STRING);
  }

  if (state == ID_DEFAULT &&
      bp->b_keywords != NULL &&
      bp->b_keywords->bqas &&
      c_now == '`')
    return (next_state = ID_BACK_STRING);

  if (state == ID_DEFAULT &&
      bp->b_keywords != NULL &&
      bp->b_keywords->sqas &&
      c_now == '\'') {
      int enable = FALSE;
    char_t z = get_at(bp, pt+1);
    point_t end = pos(bp, bp->b_ebuf);
    for(point_t i = pt+1; z != '\n' && i <= end; i++, z = get_at(bp, i)) {
      if(z == '\'') {
        enable = TRUE;
        break;
      }
    }
    if(enable)
      return (next_state = ID_SINGLE_STRING);
  }

  if (state == ID_DOUBLE_STRING && c_now == '\\') {
    skip_count = 1;
    return (next_state = ID_DOUBLE_STRING);
  }

  if (state == ID_DOUBLE_STRING && c_now == '"') {
    next_state = ID_DEFAULT;
    return ID_DOUBLE_STRING;
  }


  if (state == ID_SINGLE_STRING && c_now == '\\') {
    skip_count = 1;
    return (next_state = ID_SINGLE_STRING);
  }

  if (state == ID_DEFAULT &&
      bp->b_keywords != NULL &&
      bp->b_keywords->bqas &&
      c_now == '`')
    return (next_state = ID_BACK_STRING);

  if (state == ID_BACK_STRING && c_now == '\\') {
    skip_count = 1;
    return (next_state = ID_BACK_STRING);
  }


  if (state == ID_SINGLE_STRING && c_now == '\'') {
    next_state = ID_DEFAULT;
    return ID_SINGLE_STRING;
  }

  if (state == ID_BACK_STRING && (c_now == '`' || c_now == '\'')) {
    next_state = ID_DEFAULT;
    return ID_BACK_STRING;
  }


  if (state != ID_DEFAULT)
    return (next_state = state);

//  if (state == ID_DEFAULT && c_now >= '0' && c_now <= '9') {
//    next_state = ID_DEFAULT;
//    return (state = ID_DIGITS);
//  }

//  if (state == ID_DEFAULT && 1 == is_symbol(c_now)) {
//    next_state = ID_DEFAULT;
//    return (state = ID_SYMBOL);
//  }

  return (next_state = state);
}
